/*
 * @Description: 数据库连接
 * @Author: YangHeng
 * @Date: 2021-08-10 19:59:23
 * @FilePath: \web_server_app\mongoose\socket.js
 */
const mongoose = require('mongoose');
const querystring = require('querystring');
const { isArray } = require('core-util-is')

// 默认配置
const defaultOptions = require('./default')

// 声明一个全局唯一的值用来防止重复连接
const CONNECTION = Symbol('mongoose-connection');

class Socket {
  constructor() {
    this.config = Object.assign({}, defaultOptions, civi.config.mongo || {});
    civi.config.mongo = this.config
  }
  /**
   * @description: 数据库连接地址
   * @return {string}
   */  
  get connectionString () {
    const config = this.config;
    let connectionString = config.connectionString;
    if (!connectionString) {
      let auth = '';
      // 用户信息
      if (config.user) {
        auth = `${config.user}:${config.password}@`;
      }
      // 配置选项
      let options = '';
      if (config.options) {
        options = '?' + querystring.stringify(config.options);
      }
      // 主机信息
      let hostStr = '';
      if (isArray(config.host)) {
        hostStr = config.host.map((item, i) => {
          return `${item}:${(config.port[i] || config.port[0])}`;
        }).join(',');
      } else {
        hostStr = config.host + ':' + config.port;
      }
      // 拼接完整连接字符串
      connectionString = `mongodb://${auth}${hostStr}/${config.database}${options}`;
    }
    return connectionString
  }
  /**
   * @description: 创建数据库连接
   * @return {mongoose.Connection}
   */
  create () {
    // 已存在连接对象直接返回
    if (this[CONNECTION]) return this[CONNECTION];

    // 获取配置
    const config = this.config;
    const connectionString = this.connectionString;
    const opts = Object.assign({useUnifiedTopology: true, useFindAndModify: true}, config.options || {});
    civi.logs.info(connectionString)

    // 创建连接
    opts.useNewUrlParser = true;
    const connection = mongoose.createConnection(connectionString, opts);

    // 处理连接回调
    connection.on('error', civi.logs.error);
    connection.on('connected', () => {});
    connection.on('disconnected', () => {
      civi.logs.warn(`Mongoose connection disconnected`);
    });

    this[CONNECTION] = connection;
    return connection
  }
}

module.exports = new Socket()